package com.gitee.ywj1352.server.factory.impl;

import com.gitee.ywj1352.common.util.ServerStructure;
import com.gitee.ywj1352.server.ServerParser;
import com.gitee.ywj1352.server.anno.YWJService;
import com.gitee.ywj1352.server.biz.HiServer;

import java.lang.reflect.Method;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;
import java.util.stream.Stream;

public class DefaultServerParser implements ServerParser {

    private ConcurrentHashMap<Class<?>, ServerStructure> serverClazzCache = new ConcurrentHashMap<>();

    @Override
    public synchronized <T> ServerStructure parse(Class<T> serverClazz, Object serverInstance) {
        if (!checkInstance(serverClazz, serverInstance)) {
            throw new RuntimeException("it not interface");
        }
        if (serverClazzCache.containsKey(serverClazz)) {
            return serverClazzCache.get(serverClazz);
        }
        Method[] declaredMethods = serverClazz.getDeclaredMethods();
        Map<String, ServerStructure.MethodStructure> map = Stream.of(declaredMethods).map(m -> {
            ServerStructure.MethodStructure methodStructure = new ServerStructure.MethodStructure();
            methodStructure.setMethod(m);
            methodStructure.setName(m.getName());
            Class<?>[] parameterTypes = m.getParameterTypes();
            methodStructure.setParamsType(parameterTypes);
            methodStructure.setReturnClazz(m.getReturnType());
            return methodStructure;
        }).collect(Collectors.toMap(ServerStructure.MethodStructure::getName, c -> c));
        YWJService annotation = serverClazz.getAnnotation(YWJService.class);
        ServerStructure serverStructure = new ServerStructure();
        serverStructure.setServerClazz(serverClazz);
        serverStructure.setServerObj(serverInstance);
        serverStructure.setServiceName(annotation.serverName());
        serverStructure.setMap(map);
        serverClazzCache.put(serverClazz, serverStructure);
        return serverStructure;
    }

    private <T> boolean checkInstance(Class<T> clientClazz, Object obj) {
        return clientClazz.isInstance(obj) && clientClazz.getAnnotation(YWJService.class) != null;
    }


    public static void main(String[] args) {
        HiServer hiServer = new HiServer();
        DefaultServerParser defaultServerParser = new DefaultServerParser();
        ServerStructure parse = defaultServerParser.parse(HiServer.class, hiServer);
        System.out.println(parse);
    }
}
